package com.chcit.share.security.token.filter;

import com.chcit.share.security.ChcitToken;
import com.chcit.share.security.ChcitUser;
import com.chcit.share.security.SecurityProperties;
import com.chcit.share.security.constant.SecurityConstants;
import com.chcit.share.security.util.TokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


/**
* Description 登录认证检查过滤器
* @author liuyang
* @createDate 2019/4/4
**/
@Slf4j
public class ChcitTokenAuthenticationFilter extends BasicAuthenticationFilter {


   private SecurityProperties securityProperties;

    private UserDetailsService userDetailService;
    @Autowired
    CacheManager cacheManager;

    public ChcitTokenAuthenticationFilter(AuthenticationManager authenticationManager, SecurityProperties securityProperties,
                                          UserDetailsService userDetailsService) {
        super(authenticationManager);
        this.securityProperties = securityProperties;
        this.userDetailService = userDetailsService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
    	// 获取token, 并检查登录状态
        String token = TokenUtils.getToken(request);
        boolean notValid = StringUtils.isBlank(token); 
        if (notValid || SecurityContextHolder.getContext().getAuthentication()!=null ) {
        	//当前已认证的不做处理
            chain.doFilter(request, response);
            return;
        }
        setAuthentication(token, request,response);
        chain.doFilter(request, response);
    }

    @SuppressWarnings("unchecked")
	private void setAuthentication(String headerToken,HttpServletRequest request, HttpServletResponse response) {

         if(!securityProperties.isJwtToken()){
        	 //普通令牌，从缓存中获取用户名
            ChcitToken tokenUser = (ChcitToken) cacheManager.getCache(SecurityConstants.TOKEN_CACHE_NAME).get(headerToken).get();
            if(tokenUser!=null){
            	if (tokenUser.getExpireTime()>0 && tokenUser.getExpireTime()<System.currentTimeMillis()) {
            		//token已失效
            	}
            	else {
	                String username = tokenUser.getUsername();
	                try {
		                //重新设置失效时间
		                tokenUser.setExpireTime(System.currentTimeMillis()+securityProperties.getTokenExpireTime()*60*1000);
	                	ChcitUser user = (ChcitUser)userDetailService.loadUserByUsername(username);
	                	user.setToken(tokenUser);
		                SecurityContextHolder.getContext().setAuthentication(new ChcitAuthenticatioToken(
		                		user , null,user.getAuthorities(),headerToken));

	                }catch (Throwable t) {
	                	log.warn("获取用户失败：" + username, t);

	                }
            	}
            }
        }else{
    		// 获取令牌并根据令牌获取登录认证信息
    		Authentication authentication = TokenUtils.getAuthenticationeFromToken(headerToken);
    		// 设置登录认证信息到上下文
    		if(authentication != null){
    			SecurityContextHolder.getContext().setAuthentication(authentication);
    		}
        }
    }
    
}